package com.allenyuan.gui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JScrollPane;

import com.allenyuan.render.Renderer;
import com.allenyuan.render.ScreenRenderer;
import com.allenyuan.renderobject.RenderCircle;
import com.allenyuan.renderobject.RenderLine;
import com.allenyuan.renderobject.RenderObject;
import com.allenyuan.renderobject.RenderPath;
import com.allenyuan.renderobject.RenderPoint;
import com.allenyuan.renderobject.RenderText;
import com.allenyuan.renderobject.RenderTransformRectangle;
import com.allenyuan.render.RenderObjectPool;
import com.allenyuan.render.RenderStroke;

public class PaintPane extends JScrollPane implements ActionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 4670434653294685028L;

	private static final int READY_STATUS = 0;
	private static final int IDLE_STATUS = 1;
	private static final int DRAWING_STATUS = 2;
	private static final int SELECTED_STATUS = 3;
	private static final int MOVING_STATUS = 4;
	private static final int READY_SELECTED_STATUS = 5;
	
	private static final int DRAWING_NONE = -1;
	private static final int DRAWING_SHAPE = 0;
	private static final int DRAWING_IMAGE = 1;
	private static final int DRAWING_TEXT = 2;
	private static final int DRAWING_RECTANGLE = 3;
	private static final int DRAWING_CIRCLE = 4;
	private static final int DRAWING_POINT = 5;
	private static final int DRAWING_LINE = 6;
	private static final int DRAWING_PATH = 7;
	private static final int DRAWING_PATH_ELEMENT = 8;
	
	private int status;
	
	private int drawingNow;
	
	private Renderer renderer;
	
	private RenderPoint lastDragPoint;
	
	/**
	 * Create the panel.
	 */
	public PaintPane() {
		setBackground(Color.white);
		status = DRAWING_NONE;
		renderer = new ScreenRenderer();
		this.addMouseListener(paintPaneMouseListener);
		this.addMouseMotionListener(paintPaneMouseMotionListener);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		System.out.println(e.getActionCommand());
		quitReadyMode();
		switch (e.getActionCommand()) {
		case PaintMainFrame.LINE_ACTION_CMD:
			enterReadyMode(DRAWING_LINE);
			break;
		case PaintMainFrame.CIRCLE_ACTION_CMD:
			enterReadyMode(DRAWING_CIRCLE);
			break;
		case PaintMainFrame.IMAGE_ACTION_CMD:
			enterReadyMode(DRAWING_IMAGE);
			break;
		case PaintMainFrame.BEZIER_ACTION_CMD:
			enterReadyMode(DRAWING_PATH);
			break;
		case PaintMainFrame.TEXT_ACTION_CMD:
			enterReadyMode(DRAWING_TEXT);
			break;
		case PaintMainFrame.MOUSE_ACTION_CMD:
			enterReadyChangeMode();
			break;
		default:
			status = IDLE_STATUS;
			break;
		}
	}
	
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		ScreenRenderer r = (ScreenRenderer) renderer;
		r.setGraphics((Graphics2D)g);
		// r.setStroke(new RenderStroke(true, 10));
		RenderObjectPool.getInstance().render(r);
	}
	
	private void enterReadyMode(int drawingNow) {
		status = READY_STATUS;
		this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
		this.drawingNow = drawingNow;
	}
	
	private void quitReadyMode() {
		status = IDLE_STATUS;
		this.setCursor(Cursor.getDefaultCursor());
		this.drawingNow = DRAWING_NONE;
	}
	
	private void enterReadyChangeMode() {
		status = READY_SELECTED_STATUS;
	}
	
	private void quitDrawingMode() {
		status = READY_STATUS;
	}
	
	private void enterDrawingMode() {
		status = DRAWING_STATUS;
	}
	
	private void enterMovingMode() {
		status = MOVING_STATUS;
	}
	
	private void quitMovingMode() {
		status = SELECTED_STATUS;
	}
	
	private void enterSelectedMode() {
		status = SELECTED_STATUS;
	}
	
	private void quitSelectedMode() {
		status = READY_SELECTED_STATUS;
	}
	
	private MouseListener paintPaneMouseListener = new MouseListener() {
		
		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			if (e.getButton() == MouseEvent.BUTTON1) {
				if (status == DRAWING_STATUS) {
					RenderObjectPool.getInstance().drawProgressLastObect(RenderObject.MOUSE_RELEASE, new RenderPoint(e.getX(), e.getY()));
					quitDrawingMode();
				}
				else if (status == MOVING_STATUS) {
					quitMovingMode();
				}
			}
		}
		
		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			if (e.getButton() == MouseEvent.BUTTON1) {
				if (status == READY_STATUS) {
					RenderObject renderObject = RenderObject.create(drawingNow);
					RenderObjectPool.getInstance().addRenderObject(renderObject, RenderObjectPool.RENDER_LIST_DATA);
					RenderObjectPool.getInstance().drawProgressLastObect(RenderObject.MOUSE_PRESS, new RenderPoint(e.getX(), e.getY()));
					enterDrawingMode();
					repaint();
				}
				else if (status == SELECTED_STATUS) {
					lastDragPoint = new RenderPoint(e.getX(), e.getY());
					enterMovingMode();
					repaint();
				}

			}
		}
		
		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			if (e.getButton() == MouseEvent.BUTTON1) {
				// selected status
				if (status == READY_SELECTED_STATUS || status == SELECTED_STATUS) {
					quitSelectedMode();
					RenderObjectPool.getInstance().setNoSelect();
					RenderObject renderObj = RenderObjectPool.getInstance().getLastContainPoint(new RenderPoint(e.getX(), e.getY()));
					if (renderObj == null || renderObj.isSelected()) {
						repaint();
						return;
					}
					enterSelectedMode();
					RenderObjectPool.getInstance().addRenderObject(new RenderTransformRectangle(renderObj), RenderObjectPool.RENDER_LIST_TRANSFORM);
					renderObj.setSelected(true);
					repaint();
				}
				else if (status == DRAWING_STATUS) {
					RenderObjectPool.getInstance().drawProgressLastObect(RenderObject.MOUSE_CLICK, new RenderPoint(e.getX(), e.getY()));
				}
			}
		}
	};
	
	private MouseMotionListener paintPaneMouseMotionListener = new MouseMotionListener() {
		
		@Override
		public void mouseMoved(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void mouseDragged(MouseEvent e) {
			// TODO Auto-generated method stub
			if (status == DRAWING_STATUS) {	
				System.out.println(e.getPoint());
				RenderObjectPool.getInstance().drawProgressLastObect(RenderObject.MOUSE_DRAG, new RenderPoint(e.getX(), e.getY()));			
				repaint();
			}
			else if (status == MOVING_STATUS) {
				RenderObjectPool.getInstance().moveSelectedObject(e.getX() - lastDragPoint.getX(), e.getY() - lastDragPoint.getY());
				lastDragPoint.setX(e.getX());
				lastDragPoint.setY(e.getY());
				repaint();
			}
		}
	};

}
